/**
 * @file gprs.c
 * @Synopsis  电子价签的gprs模块控制程序，主要包括AT解析，发送
 *            GPRS数据,当前GPRS模块没有用线程独立管理，直接提供
 *            API让上层应用访问，所以设备状态由应用层管理。
 * @author SWFighter
 * @version 1.0.0V
 * @date 2018-07-13
 */
#include "rtthread.h"
#include "gprs.h"
#include "comm.h"
#include "stdlib.h"
#include "string.h"
#include "rtdevice.h"
#include "appconfig.h"
#include "epd_show.h"

#ifdef USEING_DEBUG_GPRS
#define rt_kprintf       rt_kprintf
#else
#define rt_kprintf(...)       
#endif


#define  GPRS_UART_NAME				  			"uart2"

#define  AT_ACK_OK                    "OK\r\n"
#define  AT_ACK_ERROR                 "ERROR\r\n"

static rt_uint8_t gsmType = 0;
/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  AT链接指令返回的结果
 */
/* ----------------------------------------------------------------------------*/
static const char *ATLinckOK[] = 
{
  "3",
  "CONNECT OK\r\n",//AT命令链接成功
  "ALREADY CONNECT\r\n",
  //"OK",
  "CONNECT"//透传时候链接成功
};

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  AT断开链接指令返回的结果
 */
/* ----------------------------------------------------------------------------*/
static const char *ATUnlinkOK[] = 
{
  "1",
  "CLOSE OK\r\n"
};


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis AT 命令集合 
 */
/* ----------------------------------------------------------------------------*/
const char AT_CMD[][40] = 
{
  "AT",
	"AT+CGMR",
  "AT+CPIN?",
  "AT+COPS?",
  "AT+CSQ",
  "AT+CGDCONT=1,\"IP\",\"CMNET\"",
  "AT+CGATT=1",
  "AT+CIPHEAD=1",
  "AT+CIPSTART=\"TCP\",\"120.24.229.246\",\"80\"",
  "AT+CIPSEND",
  "AT+CIPCLOSE",
  "AT+CIPCSGP=1, \"CMNET\"",
  "AT+CIPSHUT",
  "AT+CDNSORIP=0",
  "AT+CPOWD=1",
  "AT+CIURC=1",
  "AT+CSTT",
  "AT+CIICR",
  "AT+CIPSTATUS",
  "AT+CSTT",
  "AT+CIFSR",
  "AT+CIPSEND?",
  "AT+CGREG=1",
  "AT+CIPQSEND?",
  "AT+CIPQSEND=0",
  "AT+CGCLASS?",
  "AT+CLPORT=\"TCP\",\"8080\"",
  "AT+CIPMUX?",
  "AT+IFC?",
  "AT+CIPPING=\"lijun.b.diyeasy.com.cn\"",
  "AT+CIPMODE=0",
  "AT+CIPMODE=1",
  "+++",
  "ATO",
  "AT+CGMSCLASS=8",
  "AT+CIPCCFG=8,1,1460,1,0,1460,20",//8次重发，收到数据后100ms发送，最大发送1460个字节，开启转义字符，输出数据倒串口没有时间间隙，接受大小，输出间隙
  //"AT+CIPCCFG=8,1,64,1",
  "AT+CIPSHUT",//关闭移动梦网
};

static rt_uint8_t gsm_status = 0;

static rt_uint8_t* gsm_status_get(void)
{
	return &gsm_status;
}

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  发送AT命令，可以等待返回结果
 *
 * @Param at  AT命令
 * @Param buf 返回buf
 * @Param wait 等待等待时间
 *
 * @Returns 0 执行正常 -1 执行异常
 */
/* ----------------------------------------------------------------------------*/
rt_int8_t gsm_send_at(int at,rt_uint8_t *buf,rt_uint32_t wait)
{
  int ssize = 0;
  int outtime;
  rt_int8_t result;
  rt_uint8_t *temp;
  rt_device_t  dev;


  temp = buf;
  result = -1;

  dev = rt_device_find(GPRS_UART_NAME);
  RT_ASSERT(dev);

  RT_ASSERT(buf);
  rt_memset(buf, 0, GSM_READ_LEN);
  rt_kprintf(">>> %s\n",AT_CMD[at]);
  ssize = rt_device_write(dev,0,AT_CMD[at],rt_strlen(AT_CMD[at]));
  if(ssize != rt_strlen(AT_CMD[at]))
  {
    rt_kprintf("GSM Write uart error\n");
    //rt_device_close(dev);
    return -1;
  }

  rt_device_write(dev,0,"\r\n",rt_strlen("\r\n"));

  outtime = wait;
  do
  {
    int rsize;

    rt_thread_delay(1);
    rsize =rt_device_read(dev,0,temp,GSM_READ_LEN);
    if(rsize != 0)
    {
      temp += rsize;
      if((temp - buf) > GSM_READ_LEN)
      {
        rt_kprintf("AT return Data len error\n");
        RT_ASSERT(RT_NULL);
      }
      if(rt_strstr((const char *)buf,AT_ACK_OK) != NULL)
      {
        result = 0;
        //rt_kprintf("<<< %s outime = %d\n",buf,outtime);
        break;
      }
      else if(rt_strstr((const char *)buf,AT_ACK_ERROR) != NULL)
      {
        result = -1;
        break;
      }
    }
  }while(outtime--);
  rt_kprintf("<<< %swait=%d outime=%d\n",buf,wait,outtime);//显示返回结果

  return result;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  发送AT命令没有返回值
 *
 * @Param cmd AT命令
 * @Param arg AT命令带有可变参数，采用这个参数传入
 *
 * @Returns  0 执行正常 -1 执行异常
 */
/* ----------------------------------------------------------------------------*/
int gsm_send_cmd(int cmd,rt_uint8_t *arg)
{
  int ssize ;
  rt_device_t dev;

  dev = rt_device_find(GPRS_UART_NAME);
  RT_ASSERT(dev);

  if(arg == RT_NULL)
  {
    rt_kprintf(">>> %s\n",AT_CMD[cmd]);
    ssize = rt_device_write(dev,0,AT_CMD[cmd],rt_strlen(AT_CMD[cmd]));
    if(ssize != rt_strlen(AT_CMD[cmd]))
    {
      rt_kprintf("GSM Write uart error\n");
      return -1;
    }
  }
  else
  {
    rt_kprintf(">>> %s\n",arg);
    ssize = rt_device_write(dev,0,arg,rt_strlen((const char *)arg));
    if(ssize != rt_strlen((const char *)arg))
    {
      rt_kprintf("GSM Write uart error\n");
      return -1;
    }
  }

  if(cmd != AT_EXITDAT)
  {
    rt_device_write(dev,0,"\r\n",rt_strlen("\r\n"));
  }

  return 0;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  从GSM读取字符串
 *
 * @Param dev GSM读取的设备通常指串口
 * @Param buf 接收缓存
 * @Param end[] 收到特殊的返回字符串马上退出接收
 * @Param wait 最长等待时间
 *
 * @Returns 剩余等待时间 =-1表示异常
 */
/* ----------------------------------------------------------------------------*/
int gsm_recv_string(rt_device_t dev,rt_uint8_t *buf,const char *end[],long wait)
{
  rt_uint8_t *temp;
  rt_int16_t  result = -1;
  rt_uint32_t outtime;

  RT_ASSERT(buf);
  RT_ASSERT(end);

  rt_memset(buf,0,GSM_READ_LEN);
  outtime = wait;
  result = 0;
  temp = buf;
  rt_memset(temp,0,rt_strlen((const char *)temp));
  do
  {
    int rsize;
    int i;

    rsize = rt_device_read(dev,0,temp,1);
    if(rsize != 0)
    {
    	if(outtime < wait)
    	{
				outtime++;
			}
      
      //rt_kprintf(">>>%c\n",*temp);
      temp += rsize;
      if((temp - buf) > GSM_READ_LEN)
      {
        rt_kprintf("AT return Data len error\n");
        RT_ASSERT(RT_NULL);
      }
      for(i=0;i<*end[0]-0x30;i++)
      {
        if(rt_strstr((const char *)buf,(const char *)end[i+1]) != NULL)
        {
          result = i+1;
          rt_kprintf("succeed !!! outime=%d\n %s\n",outtime,buf);
          result = outtime;
          return result;
        }
        else
        {
          result = -1;
        }
      }
      if(rt_strstr((const char *)buf,AT_ACK_ERROR) != NULL)
      {
        rt_kprintf("ERROR !!!outime=%d\n %s\n",outtime,buf);
        return -2;
      }
    }
    else
    {
      if(wait > 1000)
      {
        rt_thread_delay(1);
      }
      else
      {
        rt_thread_delay(1);
      }
    }
  }while(outtime--);
  rt_kprintf("<<< %s wait=%d outime=%d ERROR!!!\n",buf,wait,outtime);

  return result;
}

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  gsm设置gprs链接服务器
 */
/* ----------------------------------------------------------------------------*/
static void gsm_set_gprs_conn(void)
{
	rt_uint8_t *status;

	status = gsm_status_get();
	(*status) |= GSM_IS_CONN;//GSM 联网
	rt_kprintf("GSM CONN GPRS OK\n");
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  gsm设置gprs退出服务器链接
 */
/* ----------------------------------------------------------------------------*/
static void gsm_set_gprs_exit(void)
{
	rt_uint8_t *status;

	status = gsm_status_get();
	(*status) &= ~GSM_IS_CONN;//GSM 联网
	rt_kprintf("GSM EXIT GPRS !!!\n");
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  gsm模块联网状态
 *
 * @Returns  RT_TRUE 已经链接  RT_FALST 链接断开
 */
/* ----------------------------------------------------------------------------*/
static rt_bool_t gsm_link_status(void)
{
	rt_uint8_t *status;

	status = gsm_status_get();
	if((*status) & GSM_IS_CONN)//如果是链接服务器的
	{
		return RT_TRUE;
	}
	return RT_FALSE;
}


//rt_uint8_t gprs_url[32]="118.184.176.34";

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  链接服务器url
 *
 * @Param cmd 0断开当前链接 1链接服务器
 * @Param url 服务器的url
 * @Param port 服务器端口
 * @Param wait 链接等待时间
 *
 * @Returns  0 正常 -1 异常 
 */
/* ----------------------------------------------------------------------------*/
rt_int8_t gsm_gprs_connect(int cmd,char *url,int port,int wait)
{
  rt_int16_t result =-1;
  rt_device_t dev;
  rt_uint8_t *recv_buf,*recv_head;

	//如果已经链接了网络则不需要做任何处理
	if(cmd == 1)
	{
		if(gsm_link_status() == RT_TRUE)
		{
			rt_kprintf("GSM IS CONN GPRS\n");
			return 0;
		}
	}
  result = 0;
  dev = rt_device_find(GPRS_UART_NAME);
  recv_head = recv_buf = rt_calloc(1,GSM_READ_LEN);
  RT_ASSERT(recv_buf);

  // 断开连接
  if(cmd == 0)
  {
    gsm_send_cmd(AT_CIPCLOSE,RT_NULL);

    result = gsm_recv_string(dev,recv_buf,ATUnlinkOK,1000);
    if(result > 0)
    {
      result = 0;
    }
    else
    {
      result = -1;
    }
		gsm_set_gprs_exit();//设置GPRS断网
    //system_delay_ms(100);
  }
  else if(cmd == 1)
  {    
    gsm_send_at(AT_CIPHEAD,recv_buf,500);

    if(url == NULL)
    {
      //rt_sprintf((char *)recv_buf,"AT+CIPSTART=\"TCP\",\"%s\",\"%d\"",gprs_url,port);
    }
    else 
    {
      rt_sprintf((char *)recv_buf,"AT+CIPSTART=\"TCP\",\"%s\",\"%d\"",url,port);
    }

    gsm_send_cmd(AT_CIPSTART,recv_buf);

    result = gsm_recv_string(dev,recv_buf,ATLinckOK,1000);
		if(rt_strstr((const char *)recv_buf,"STATE: TCP CLOSED") != RT_NULL)
		{
			rt_kprintf("\033[1m\033[45;33m Server TCP CLOSED \033[0m\n");
			result = -1;
			send_epd_mail(EPD_EVT_TCPAlA);//服务器拒绝链接
		}
    if(result > 0)
    {
    	gsm_set_gprs_conn();//设置GPRS链接状态
      result = 0;
    }
    else
    {
    	gsm_set_gprs_exit();//设置GPRS断网
      result = -1;
    }
  }

  rt_free(recv_head);

  return result;
}

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  GPRS链接服务器，链接失败自动重连3次
 *
 * @Param fun  gprs链接服务器函数
 * @Param cmd  AT命令
 * @Param url  服务器url
 * @Param port 服务器端口
 * @Param wait 超时等待时间
 *
 * @Returns   
 */
/* ----------------------------------------------------------------------------*/
rt_err_t gprs_connet_resend(rt_int8_t (*fun)(int ,char *,int ,int),int cmd,char *url,int port,int wait)
{
	rt_uint8_t run;
	rt_int8_t result;
	
	run = 3;
	do
	{
		result = fun(cmd,url,port,wait);
		if(result == 0)
		{
			return RT_EOK;
		}
	}while(run--);

	return RT_ERROR;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis GSM 透传模式与命令模式切换 
 *
 * @Param mode  1透传模式 0命令模式
 * @Param rbuf  读取缓存，暂时没用
 *
 * @Returns   
 */
/* ----------------------------------------------------------------------------*/
int gsm_switch_cmd(rt_uint8_t mode,rt_uint8_t *rbuf)
{
  rt_int8_t result;



  if(mode == 1)//透传模式
  {
    result = gsm_send_at(AT_ATO,rbuf , 100);
  }
  else //退出透传模式
  {
    rt_thread_delay(101);
    result = gsm_send_cmd(AT_EXITDAT, RT_NULL);
    rt_thread_delay(101);
  }

  return result;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis 用透传模式发送GPRS数据 
 *
 * @Param sBuf  发送数据缓存
 * @Param ssize 发送数据缓存大小
 * @Param rBuf  接收数据缓存
 * @Param rsize 接收数据缓存大小
 * @Param delay 发送后等待接受数据的超时时间
 *
 * @Returns  0 接收正常 -1异常 
 */
/* ----------------------------------------------------------------------------*/
rt_int8_t gsm_send_gprs_OSPF(rt_uint8_t *sBuf,rt_uint16_t ssize,rt_uint8_t *rBuf,rt_uint16_t *rlen,rt_uint16_t delay)
{
  rt_device_t dev;
  rt_uint8_t *head;
  rt_uint16_t len=0;
  rt_uint16_t RSzie;
	rt_uint16_t rsize;

	rsize = (*rlen);

  dev = rt_device_find(GPRS_UART_NAME);//找到串口
  RT_ASSERT(dev);

  head = rBuf;

	do
	{
		RSzie = rt_device_read(dev,0,head,rsize);
	}while(RSzie);
 
  //发送数据
  rt_kprintf("%d>>>",ssize);
  show_hex_string(sBuf,ssize);
  rt_device_write(dev,0,sBuf,ssize);
  //rt_thread_delay(delay);
  while(delay--)
  {
    RSzie = rt_device_read(dev,0,head,rsize);
    if(RSzie == 0)//没有收到数据
    {
			if((len != 0) && ((head - rBuf) == (len)))//服务器发送的长度
			{
				//rt_kprintf("head recv data len = %d\n",len);
				break;
			}
			rt_thread_delay(1);
    }
    else//接受到数据
    {
      head += RSzie;
      if((head - rBuf) >= rsize)//收到数据
      {
      	len = rsize;
        rt_kprintf("recv data len=%d\n",len); 
        break;
      }
			if(((head-rBuf)>=2)&&(len == 0))//只解析一次服务器返回的数据长度
			{
        len = rBuf[0];
        len <<= 8;
        len += rBuf[1];
				rt_kprintf("len=%d\n",len); 
				len += 2;//TCP包长度
				if(len > rsize)//服务器返回的数据比内存还大丢弃
				{
					rt_kprintf("sever ack len > recv size!!!\n");
					len = rsize;
				}
			}
    }
  }
  if(delay <= 0)
  {
    return -1;
  }

	(*rlen) = len;
  rt_kprintf("%d<<<",(len));
  show_hex_string(rBuf, len);

	if(len <= 0)
	{
		return -1;
	}
  return 0;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis    GPRS发送数据，发送失败自动重发三次
 *
 * @Param sBuf  发送缓存
 * @Param ssize 发送大小
 * @Param rBuf  接收缓存
 * @Param rlen  接收大小
 * @Param delay 超时时间
 *
 * @Returns   
 */
/* ----------------------------------------------------------------------------*/
rt_int8_t rsend_gprs_data(rt_uint8_t *sBuf,rt_uint16_t ssize,rt_uint8_t *rBuf,rt_uint16_t *rlen,rt_uint16_t delay)
{
	rt_uint8_t run;
	rt_int8_t result;
	
	run = GPRS_RSEND_MAX;
	do
	{
		result = gsm_send_gprs_OSPF(sBuf,ssize,rBuf,rlen,delay);
		if(result == 0)
		{
			return 0;
		}
	}while(run--);

	return -1;
}

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  操作gprs模块在rthtread系统中的串口，只需要打开一次
 *
 * @Param value 1打开 0 关闭
 *
 * @Returns  0 正常 
 */
/* ----------------------------------------------------------------------------*/
int gprs_module_uart_crl(rt_uint8_t value)
{
  rt_device_t dev;
  rt_uint8_t result = 0;

  dev =  rt_device_find(GPRS_UART_NAME);
  if(dev != RT_NULL)
  {
    if(value == 1)
    {
      result = rt_device_open(dev, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX | 
          RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_DMA_RX);
      RT_ASSERT(result == RT_EOK);
    }
    else 
    {
      rt_device_close(dev);
    }
  }
  else
  {
    rt_kprintf("none %s device\n");
  }

  return result;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  从gsm模块读取数据，只是简单的读取
 *
 * @Param recv 接收缓存
 * @Param size 缓存大小
 *
 * @Returns  读取数据字节数量 
 */
/* ----------------------------------------------------------------------------*/
int gprs_uart_read(rt_uint8_t *recv,rt_uint32_t size)
{
  rt_device_t dev;

  dev = rt_device_find(GPRS_UART_NAME);
  RT_ASSERT(dev);

  rt_memset(recv, 0, size);
  size = rt_device_read(dev,0,recv,size);
  //rt_kprintf("size = %d\n",size);

  return size; 
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  解析获取gsm的信号值
 *
 * @Param buf AT+CSQ指令的返回字符串 
 *
 * @Returns   信号质量 0-30
 */
/* ----------------------------------------------------------------------------*/
static rt_int8_t get_gsm_CSQ(rt_uint8_t *buf)
{
  rt_int8_t csq;
  rt_uint8_t *head,*end;
  rt_uint8_t str[3] = {0};

  if(rt_strstr((const char *)buf,"+CSQ:") != NULL)
  {
    //rt_strstr(buf,"AT+CSQ\r\n+CSQ: %d,",&csq);
    head = (rt_uint8_t *)rt_strstr((const char *)buf,": ");
    end = (rt_uint8_t *)rt_strstr((const char *)buf,",");
    //rt_kprintf("head:%s\n",head);
    //rt_kprintf("head:%s\n",end);
    if(head != NULL && end != RT_NULL)
    {
      head += rt_strlen(": ");
      if((end - head > 0) && (end - head < 3))
      {
        rt_memcpy(str, head, end - head);
        rt_kprintf("csq %d\n",atoi((const char *)str));
        csq = atoi((const char *)str);
      }
      else
      {
        csq = -1;//没有返回
      }
    }
    else
    {
      csq = -1;
    }
  }
  else
  {
    //rt_kprintf("none csq\n");
    csq = -1;
  }
  return csq;
} 


#define  GSM_CMD_ERRMAX  5
/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  GSM 模块开机处理 
 *
 * @Param curCsq 获取当前信号值的指针
 * @Param mode 初始化为透传模式 0 cmd  1透传
 *
 * @Returns 执行结果0 正常  -1异常  -2没有SIM卡 
 */
/* ----------------------------------------------------------------------------*/
rt_int8_t gprs_module_start(rt_int8_t *curCsq,rt_uint8_t mode)
{
  rt_uint8_t  *recv,*head;
  rt_uint8_t  run = 100;
  rt_uint8_t  finshFlag  = 0;
  rt_int8_t   result = 0;
  rt_int16_t  cmdResult = 0;
	rt_uint8_t  *status;
	rt_uint8_t  errorNum = 0;
	rt_uint16_t csqDelay = 0;

	status = gsm_status_get();
	if((*status) & GSM_IS_WORK)//模块已经工作就不需要重启。
	{
		rt_kprintf("GSM Is Work\n");
		return 0;
	}

  head = recv = rt_calloc(1,GSM_READ_LEN);
  RT_ASSERT(recv);

  //设置模块关机
  gsm_send_at(AT_CPOWD,recv,20);
  rt_kprintf(">>>:%s\n",recv);

  rt_pin_mode(GSM_POWR_PIN,PIN_MODE_OUTPUT);	//电源脚配置
  rt_pin_mode(GSM_SW_PIN,PIN_MODE_OUTPUT); //开机脚配置	
GSMResetPos:
	finshFlag  = 0;//重新获取redy
	rt_kprintf("ERROR GSM CMD Num =%d\n",errorNum);
  //开启GSM
  rt_pin_write(GSM_SW_PIN, 1);//低电平，开机引脚
  rt_pin_write(GSM_POWR_PIN, 0);//关电源
  rt_thread_delay(10);
  rt_pin_write(GSM_POWR_PIN, 1);//开电源
  rt_thread_delay(5);//稳定一下电源，再开机

  rt_pin_write(GSM_SW_PIN, 0);//高电平,开机脚
  rt_thread_delay(110);
  rt_pin_write(GSM_SW_PIN, 1);//低电平，开机脚

  //rt_thread_delay(200);

  //读空串口
  gprs_uart_read(recv,GSM_READ_LEN);
  rt_kprintf("GSM Start << %s\n",recv);

  //通讯测试
  run = 10;
  while(run--)
  {
    cmdResult = gsm_send_at(AT,recv,50);
		if(cmdResult == 0)
		{
			break;
		}
  }
  if(cmdResult != 0)//重新开机
  {
  	goto GSMResetPos;
  }

  //等待注册上网络
  run = 100;
  while(run--)
  {
  	rt_int16_t recvSize = 0;
		
    rt_thread_delay(100);
    recvSize = gprs_uart_read(recv,GSM_READ_LEN);
		if(recvSize == 0)//收不到数据，模块异常需要重启
		{
			if(run > 10)
			{
				run-=10;
				result = gsm_send_at(AT,recv,20);//发送AT
				if(result != 0)//模块没反应
				{
					if(errorNum++ < GSM_CMD_ERRMAX)
					{
						rt_kprintf("GSM restart\n");
						goto GSMResetPos;
					}
				}
			}
		}
		
    rt_kprintf("%d>>>:%s\n",run,recv);
    if(rt_strstr((const char *)recv,"SMS Ready") != NULL)
    {
      finshFlag++;
    }
    else if(rt_strstr((const char *)recv,"Call Ready") != NULL)
    {
    	if(gsmType == GSM_AIR208S)
    	{
				finshFlag = 3;
			}
      finshFlag++;
    }
    else if(rt_strstr((const char *)recv,"READY") != NULL)
    {
      finshFlag++;
    }

		if(rt_strstr((const char *)recv, "NOT INSERTED") != RT_NULL)//没有插卡
		{
			rt_kprintf("\033[1m\033[45;33m NOT INSERTED SIM \033[0m\n");
			result = -2;
			send_epd_mail(EPD_EVT_NoneSIMALA);//没有SIM卡
			rt_free(head);
  		return result;
		}

		//获取模块类型
		if((gsmType == 0) && (finshFlag != 0))//默认类型GSM
		{
			result = gsm_send_at(AT_CGMM,recv,50);
			if(result == 0)//获取型号成功
			{
				if(rt_strstr((const char *)recv, "AirM2M") != RT_NULL)
				{
					gsmType = GSM_AIR208S;
				}
				else
				{
					gsmType = GSM_SIM800C;
				}
			}
		}
			
    //检测模块有没有初始化完成
    if(finshFlag >= 3)
    {
      //gsm_send_at(AT,recv,20);
      //rt_thread_delay(50);
      break;
    }

    if((run%10) == 0)
    {
      result = gsm_send_at(AT,recv,20);
			if(result != 0)//模块没反应
			{
				if(errorNum++ < GSM_CMD_ERRMAX)
				{
					rt_kprintf("GSM restart\n");
					goto GSMResetPos;
				}
			}
    }

    //检查是否真的启动
    if(run < 3)
    {
      result = gsm_send_at(AT,recv,100);
      if(result != 0)//启动失败
      {
        rt_kprintf("reset gsm module\n");
        rt_pin_write(GSM_POWR_PIN, 0);
				if(errorNum++ < GSM_CMD_ERRMAX)
				{
					goto GSMResetPos;
				}
      }
    }
  }

  //检测模块的信号
  run = 80;
  while(run--)
  {
    rt_int8_t csq;

    cmdResult = gsm_send_at(AT_CSQ,recv,100);
		if(cmdResult == -1)//模块异常
		{
			rt_kprintf("errorNUm = %d\r\n",errorNum);
			if(errorNum++ > GSM_CMD_ERRMAX)
			{
				goto GSMResetPos;//重启模块
			}
		}
    csq = get_gsm_CSQ(recv);
    if(csq > 0)
    {
      (*curCsq) = csq;	
			if(csq < 10)//信号衰弱
			{
				rt_uint16_t value;
				
				rt_kprintf("\033[1m\033[45;33m CSQ too small \033[0m\n");
				//屏幕显示信号差
				value = load_bkp_sysinfo();
				value |= SYS_CSQALA_HINT;
				save_bkp_sysinfo(value);
				send_epd_mail(EPD_EVT_CSQAlA);//显示电池欠压标记
				csqDelay = 500;
				rt_thread_delay(100+csqDelay);//多等待一会
			}
			else if(csq < 11)
			{
				csqDelay = 300;
				rt_thread_delay(csqDelay);
			}
			else if(csq < 12)
			{
				csqDelay = 200;
				rt_thread_delay(csqDelay);
			}
			else if(csq < 13)
			{
				csqDelay = 150;
				rt_thread_delay(csqDelay);
			}
			else if(csq < 15)
			{
				csqDelay = 100;
				rt_thread_delay(csqDelay);
			}
      break;
    }
	else //没信号
	{
		rt_thread_delay(45);
	}
	rt_thread_delay(5);
  }
  if(run == 0)//信号获取不到重启模块
  {
		if(errorNum++ < GSM_CMD_ERRMAX)//重新启动
		{
			goto GSMResetPos;
		}
		else //错误次数太多
		{
			rt_free(head);
			return -1;		
		}
  }

	
GSMInitSetPos:
  //gsm_send_at(AT_CGCLASS,recv,100);
  if(mode == 1)//透传模式
  {
    cmdResult |= gsm_send_at(AT_CIPMODE1, recv, 100);//透传模式
		rt_thread_delay(1); //延时等待串口,否则出乱码
    cmdResult |= gsm_send_at(AT_CIPCCFG,recv , 100);//配置
    rt_thread_delay(1);
  }
  else
  {
    cmdResult = gsm_send_at(AT_CIPMODE0, recv, 100);
  }
	rt_kprintf("cmdResult=%d",cmdResult);
	if(cmdResult != 0)
	{
		if(errorNum++ < GSM_CMD_ERRMAX)//重新启动
		{
			goto GSMResetPos;
		}
		else
		{
			rt_free(head);
			return -1;		
		}
	}
GSMGPRSCSTT:
  cmdResult |= gsm_send_at(AT_CGDCONT,recv,100);//设置PDP上下文,互联网接协议,接入点等信息
	rt_thread_delay(1+errorNum+csqDelay);
  cmdResult |= gsm_send_at(AT_CSTT,recv,500);//附着GPRS业务
	if(cmdResult != 0)
	{
		if(errorNum++ < GSM_CMD_ERRMAX)//重新启动
		{
			goto GSMResetPos;
		}
		else
		{
			rt_free(head);
			return -1;		
		}

	}
  rt_thread_delay(100+(100*errorNum)+50+csqDelay);//如果是信号问题增加延时
  cmdResult = gsm_send_at(AT_CIICR,recv,2000);//附着网络
	if(cmdResult != 0)//附着失败
	{
		gsm_send_at(AT_CIPSHUT,recv,100);//关闭移动梦网
		gsm_send_at(AT_CGDCONT,recv,100);//设置PDP上下文,互联网接协议,接入点等信息
		gsm_send_at(AT_CSTT,recv,500);//附着GPRS业务
		if(rt_strstr((const char *)recv,"+PDP: DEACT") != RT_NULL)
		{
			rt_uint16_t value;

			rt_kprintf("\033[1m\033[45;33m SIM Card No Money \033[0m\n");
			//显示没有网络
			if(errorNum >= GSM_CMD_ERRMAX)//确实连不上基站
			{
				value = load_bkp_sysinfo();
				value |= SYS_SIMALA_HINT;
				save_bkp_sysinfo(value);
				send_epd_mail(EPD_EVT_SIMAlA);//不能链接基站很可能是欠费了
			}
		}
		cmdResult = gsm_send_at(AT_CIICR,recv,1500);//附着网络
		if(cmdResult != 0)//马上重试一次如果还失败，退出启动
		{
			if(errorNum++ < GSM_CMD_ERRMAX)//重新启动
			{
				goto GSMResetPos;
			}
			else
			{
				rt_free(head);
				return -1;		
			}
		}
	}
	else//成功以后
	{
		rt_uint16_t value;
		value = load_bkp_sysinfo();
		if(value & SYS_SIMALA_HINT)//需要清除异常标志
		{
			value &= ~SYS_SIMALA_HINT;//清除标记
			save_bkp_sysinfo(value);
			send_epd_mail(EPD_EVT_FULL);//更新屏幕
		}
	}
  rt_thread_delay(100);
  gsm_send_at(AT_CIFSR,recv,20);//查询IP
  run = 3;
  while(run--)
  {
    result = gsm_send_at(AT_CGATT,recv,500);
    if(result == 0)
    {
      break;
    }
		else
		{
			rt_thread_delay(100);
		}
  }
	if(run == 0)
	{
		result = -1;
	}
	if(result == 0)
	{
		status = gsm_status_get();
		(*status) |= GSM_IS_WORK;//标记GSM在工作
		rt_kprintf("GSM Start OK %X\n",(*status));
	}
  rt_free(head);
  return result;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  GSM 模块关机
 */
/* ----------------------------------------------------------------------------*/
void gprs_module_stop(void)
{
	rt_uint8_t *status;

	status = gsm_status_get();
	(*status) = 0;//关机了
  //设置模块关机
  gsm_send_cmd(AT_CPOWD,RT_NULL);

  rt_pin_mode(GSM_POWR_PIN,PIN_MODE_OUTPUT);	//电源
  rt_pin_write(GSM_POWR_PIN, 0);

  rt_pin_mode(GSM_SW_PIN,PIN_MODE_OUTPUT); //开机脚
  rt_pin_write(GSM_SW_PIN, 1);
  rt_thread_delay(110);
  rt_pin_write(GSM_SW_PIN, 0);	

}


